package cn.com.nes.site.handle;

import cn.com.nes.common.exception.*;
import cn.com.nes.site.entity.PageData;
import cn.hutool.core.collection.CollUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {


    @ExceptionHandler({MethodArgumentNotValidException.class, BindException.class, MissingServletRequestParameterException.class, MissRequestParameterException.class})
    @ResponseBody
    public PageData handleMissRequestParameterError(Exception ex) {
        String errorMsg = "";
        if (ex instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException methodArgumentNotValidException = (MethodArgumentNotValidException) ex;
            List<FieldError> fieldErrors = methodArgumentNotValidException.getBindingResult().getFieldErrors();
            if (CollUtil.isNotEmpty(fieldErrors)) {
                Set<String> errorSet = new HashSet<String>();
                for (FieldError error : fieldErrors) {
                    errorSet.add(error.getDefaultMessage());
                }
                errorMsg = errorSet.toString();
            }
        }
        if (ex instanceof BindException) {
            BindException bindException = (BindException) ex;
            List<FieldError> fieldErrors = bindException.getBindingResult().getFieldErrors();
            if (CollUtil.isNotEmpty(fieldErrors)) {
                Set<String> errorSet = new HashSet<String>();
                for (FieldError error : fieldErrors) {
                    errorSet.add(error.getDefaultMessage());
                }
                errorMsg = errorSet.toString();
            }
        }
        if (ex instanceof MissingServletRequestParameterException) {
            MissingServletRequestParameterException missingServletRequestParameterException = (MissingServletRequestParameterException) ex;
            errorMsg = missingServletRequestParameterException.getParameterName();
        }
        if (ex instanceof MissRequestParameterException) {
            errorMsg = ex.getMessage();
        }
        return logAndReturnMissRequestParameterError(ex, errorMsg);
    }

    /**
     * 记录日志和返回请求参数错误
     * @param ex
     * @param errorMsg
     * @return
     */
    private PageData logAndReturnMissRequestParameterError(Exception ex, String errorMsg) {
        errorMsg = "请填写：" + errorMsg;
        return logMsgAndReturnMsg(ex, "请求参数错误-" + errorMsg, errorMsg);
    }


    @ExceptionHandler({BusinessException.class})
    @ResponseBody
    public PageData handleBusinessError(Exception ex) {
        String errorMsg = "";
        if (ex instanceof BusinessException) {
            errorMsg = ex.getMessage();
        }
        if (ex instanceof NoSuchEnumException) {
            errorMsg = ex.getMessage();
        }
        return logAndReturnBusinessError(ex, errorMsg);
    }

    /**
     * 记录日志和返回系统功能错误
     * @param ex
     * @param logMsg
     * @return
     */
    private PageData logAndReturnBusinessError(Exception ex, String logMsg) {
        String errorMsg = "系统功能错误";
        return logMsgAndReturnMsg(ex, errorMsg + "-" + logMsg, logMsg);
    }

    @ExceptionHandler({MissBusinessParameterException.class, IllegalBusinessException.class, ApiCallFailedException.class})
    @ResponseBody
    public PageData handleSystemFunctionValidError(Exception ex) {
        String errorMsg = "";
        if (ex instanceof MissBusinessParameterException) {
            errorMsg = "参数错误：" + ex.getMessage();
        }
        if (ex instanceof IllegalBusinessException) {
            errorMsg = "业务错误：" + ex.getMessage();
        }
        if (ex instanceof ApiCallFailedException) {
            errorMsg = "API错误：" + ex.getMessage();
        }
        return logAndReturnSystemFunctionError(ex, errorMsg);
    }

    /**
     * 记录日志和返回系统功能错误
     * @param ex
     * @param logMsg
     * @return
     */
    private PageData logAndReturnSystemFunctionError(Exception ex, String logMsg) {
        String errorMsg = "系统功能错误";
        return logMsgAndReturnMsg(ex, errorMsg + "-" + logMsg, errorMsg);
    }


    @ExceptionHandler({Exception.class, SystemException.class})
    @ResponseBody
    public PageData handleSystemError(Exception ex) {
        return logMsgAndReturnSystemError(ex, ex.getMessage());
    }

    /**
     * 记录日志和返回系统错误
     * @param ex
     * @param logMsg
     * @return
     */
    private PageData logMsgAndReturnSystemError(Exception ex, String logMsg) {
        String errorMsg = "系统错误";
        return logMsgAndReturnMsg(ex, errorMsg + "：" + logMsg, errorMsg);
    }

    /**
     * 记录日志和返回数据
     * @param ex
     * @param logMsg
     * @param returnMsg
     * @return
     */
    private PageData logMsgAndReturnMsg(Exception ex, String logMsg, String returnMsg) {
        logMsg(logMsg, ex);
        return PageData.error(returnMsg);
    }

    /**
     * 记录日志
     * @param errorMsg 错误信息描述
     * @param ex       异常
     */
    private void logMsg(String errorMsg, Exception ex) {
        log.error("{}", errorMsg, ex);
    }

}

